/*

Miranda IM: the free IM client for Microsoft* Windows*

Copyright 2000-2007 Miranda ICQ/IM project, 
all portions of this codebase are copyrighted to the people 
listed in contributors.txt.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or ( at your option ) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
aLONG with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

/**
 * Local Includes:
 **/
#include "commonheaders.h"
#include "../Resource/version.h"
#include "ctrl.h"
#include "ctrlButton.h"
#include "dlgPropsheet.h"
#include "dlgAnniversaryList.h"

#include "ex_import/svcExImport.h"
#include "svcReminder.h"
#include "svcTimezone.h"
#include "svcRefreshUserDetails.h"
#include "ExtraServices.h"

#include "menuitems.h"
#include "options.h"


/**
 * Miranda Includes:
 **/
#include "../Include/m_updater.h"

// local:

static PLUGININFOEX pluginInfo = {
	sizeof( PLUGININFOEX ),
	__PLUGIN_DISPLAY_NAME,
	__VERSION_DWORD,
	__DESC,
	__AUTHOR,
	__AUTHOREMAIL,
	__COPYRIGHT,
	__AUTHORWEB,      
	UNICODE_AWARE,
	DEFMOD_UIUSERINFO,
	MIID_UIUSERINFOEX
};

static HANDLE	ghModulesLoadedHook		= NULL;
static HANDLE	ghTopToolBarLoaded		= NULL;
static HANDLE	ghModernToolBarLoaded	= NULL;
static HANDLE ghShutdownHook				= NULL;

/*
============================================================================================
	event hooks
============================================================================================
*/

/**
 * This function is called by the ME_TTB_MODULELOADED event.
 * It adds a set of buttons to the TopToolbar plugin.
 *
 * @param	wParam	- not used
 * @param	lParam	- not used
 *
 * @return	always 0
 **/
static INT OnTopToolBarLoaded( WPARAM wParam, LPARAM lParam ) 
{
	UnhookEvent( ghTopToolBarLoaded );
	NAnniversaryList::OnTopToolBarLoaded();
	NServices::Reminder::OnTopToolBarLoaded();
	return 0;
}

/**
 * This function is called by the ME_TB_MODULELOADED event.
 * It adds a set of buttons to the Toolbar of the Modern Contact List.
 *
 * @param	wParam	- not used
 * @param	lParam	- not used
 *
 * @return	always 0
 **/
static INT OnModernToolBarLoaded( WPARAM wParam, LPARAM lParam ) 
{
	UnhookEvent( ghModernToolBarLoaded );
	NAnniversaryList::OnToolBarLoaded();
	NServices::Reminder::OnToolBarLoaded();
	return 0;
}

/**
 * This function is called by Miranda just after loading all system modules.
 *
 * @param	wParam	- not used
 * @param	lParam	- not used
 *
 * @return	always 0
 **/
static INT OnModulesLoaded( WPARAM wParam, LPARAM lParam ) 
{
#ifdef _DEBUG
	#define new DEBUG_NEW;
	int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
	tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
	_CrtSetDbgFlag( tmpFlag );
//	_CrtSetBreakAlloc(4852);
#endif
	INT ptr;

	UnhookEvent( ghModulesLoadedHook );

	myGlobals.IsCListNicer = ServiceExists( "CListFrame/SetSkinnedFrame" );
	myGlobals.HaveCListExtraIcons = ServiceExists( MS_CLIST_EXTRA_SET_ICON );

	// init meta contacts
	ptr = CallService( MS_MC_GETPROTOCOLNAME, 0, 0 );
	if( ptr != CALLSERVICE_NOTFOUND )
	{	
		myGlobals.szMetaProto = ( LPCSTR )ptr;
	}

	// options
	NOptions::LoadModule();
	// create services to receive string lists of languages and timezones
	Constants_LoadModule();
	// load module to remind user about birthday and a anniversary
	NServices::Reminder::OnModulesLoaded();
	// load extended intagration services
	NServices::SendRecvEMail::OnModulesLoaded();
	NServices::ViewHomepage::LoadModule();
	NServices::SendSMS::LoadModule();
	NServices::Gender::LoadModule();
	
#ifdef _DEBUG // new feature, not in release jet
	NServices::NAvatar::OnModulesLoaded();
#endif
	NServices::TimeZones::OnModulesLoaded();
	
	// build contact's menuitems
	MenuItems::RebuildContact();
	MenuItems::RebuildMain();

	// finally register for updater
	CallService( MS_UPDATE_REGISTERFL, ( WPARAM )__UPDATER_DOWNLOAD_ID, ( LPARAM )&pluginInfo );
	// install known modules strings to database
	DB::Setting::WriteAString( NULL, "KnownModules", MODULELONGNAME, "UserInfo,UserInfoEx,UserInfoExW" );

	return 0;
}

static INT OnShutdown( WPARAM wParam, LPARAM lParam ) 
{
	UnhookEvent( ghShutdownHook );
	NContactDetailsPS::UnLoadModule();
	NServices::Reminder::UnloadModule();

	// uninitialize classes
	CbEx_UnLoadModule();
	NCtrl::NButton::UnloadModule();

	Constants_UnloadModule();
	return 0;
}

/*
============================================================================================
	plugin interface & DllEntrypoint
============================================================================================
*/

/**
 * This function is called by Miranda to get some information about this plugin.
 *
 * @return	pointer to pluginInfo struct
 **/
extern "C" __declspec( dllexport ) PLUGININFOEX *MirandaPluginInfoEx( DWORD mirandaVersion ) 
{
	if( mirandaVersion < PLUGIN_MAKE_VERSION( 0,8,0,0 ) )
	{
		return NULL;
	}
	myGlobals.mirandaVersion = mirandaVersion;
	return &pluginInfo;
}

/**
 * This function returns the provided interfaces.
 *
 * @return	array of interfaces
 **/
extern "C" __declspec( dllexport ) const MUUID *MirandaPluginInterfaces()
{
	static const MUUID interfaces[] = {
		MIID_UIUSERINFOEX,	// this is just me
		MIID_UIUSERINFO,		// replace the default userinfo module
		MIID_CONTACTINFO,		// indicate, that MS_CONTACT_GETCONTACTINFO service is provided 
		MIID_REMINDER,			// indicate an Reminder of being provided
		MIID_SREMAIL,				// Send/Receive E-Mail service is provided
		MIID_LAST
	};
	return interfaces;
}

/**
 * This function is called by Miranda just to make it possible to unload some memory, ...
 *
 * @return	0
 **/
extern "C" INT __declspec( dllexport ) Unload( VOID )
{
	return 0;
}

/**
 * This function is called by Miranda to initialize the plugin.
 *
 * @return	0
 **/
extern "C" INT __declspec( dllexport ) Load( PLUGINLINK *link )
{
	INITCOMMONCONTROLSEX ccEx;

	if( link )
	{
		CHAR szVer[MAX_PATH] = { 0 };

		pluginLink = link;

		CallService( MS_SYSTEM_GETVERSIONTEXT, MAX_PATH, ( LPARAM )szVer );

#ifdef _UNICODE
		
		if( ( GetVersion() & 0x80000000 ) != 0 ) 
		{
			return 1;
		}
		if( ( strstr( szVer, "Unicode" ) == NULL ) ) 
		{
			return 1;
		}
#else
		if( ( strstr( szVer, "Unicode" ) != NULL ) ) 
		{
			return 1;
		}
#endif

		// init common controls
		ccEx.dwSize = sizeof( ccEx );
		ccEx.dwICC = ICC_WIN95_CLASSES|ICC_DATE_CLASSES;
		InitCommonControlsEx( &ccEx );

		ZeroMemory( &myGlobals, sizeof( MGLOBAL ) );

		// init miranda's memory interface
		if( !mir_getMMI( &mmi ) && !mir_getLI( &li ) && !mir_getUTFI( &utfi ) /*&& mir_getXI( &xi )*/ ) 
		{
			// load icon library
			NIcoLib::LoadModule();

			NServices::TimeZones::LoadModule();
			NServices::ContactInfo::LoadModule();
			NServices::SendRecvEMail::LoadModule();
			NServices::RefreshUserDetails::LoadModule();
			
			CbEx_LoadModule();
			// load my button class
			NCtrl::NButton::LoadModule();
			// load vcard module
			NExImport::LoadModule();
			// load the UserInfoPropertySheet module
			NContactDetailsPS::LoadModule();
			
			// Anniversary stuff
			NAnniversaryList::LoadModule();
			NServices::Reminder::LoadModule();

			// Now the module is loaded! Start initializing certain things
			ghModulesLoadedHook = HookEvent( ME_SYSTEM_MODULESLOADED, OnModulesLoaded );
			ghTopToolBarLoaded = HookEvent( ME_TTB_MODULELOADED, OnTopToolBarLoaded );
			ghModernToolBarLoaded = HookEvent( ME_TB_MODULELOADED, OnModernToolBarLoaded );
			ghShutdownHook = HookEvent( ME_SYSTEM_SHUTDOWN, OnShutdown );
			return 0;
		}
	}
	return 1;
}

/**
 * Windows needs it for loading.
 *
 * @return	TRUE
 **/
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD fdwReason, LPVOID lpvReserved )
{
	switch( fdwReason ) {
		case DLL_PROCESS_ATTACH:
			ghInst = hinst;
			break;
	}
	return TRUE;
}

